package com.ynet.middleground.user.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.dozer.Mapper;
import org.springframework.beans.BeanUtils;

/**
 * @author liulx
 * @description 对象处理工具类
 * @date 2019-10-11 16:46
 */
public class BeanUtil {

    /***
     * 转化显示Bean
     *
     * @param list 待转化列表
     * @param clazz 目标类
     * @param <T>
     * @return 转化后的List
     * @throws Exception
     */
    public static <T> List<T> listToBeanVo(List list, Class<T> clazz, String... ignoreProperties) throws Exception {
        List<T> resultList = new ArrayList<>();
        if (list == null) {
            return resultList;
        }

        for (Object obj : list) {
            T t = objToBeanVo(obj, clazz, ignoreProperties);
            resultList.add(t);
        }

        return resultList;
    }

    /**
     * 复制源对象属性到目标对象
     *
     * @param obj 源对象
     * @param clazz 目标类型
     * @param ignoreProperties 需忽略属性列表
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> T objToBeanVo(Object obj, Class<T> clazz, String... ignoreProperties) throws Exception {
        T t = (T)Class.forName(clazz.getName()).newInstance();
        BeanUtils.copyProperties(obj, t, ignoreProperties);
        return t;
    }

    /**
     * 封装dozer处理集合的方法：List<S> --> List<T>
     */
    public static <T, S> List<T> mapList(Mapper mapper, List<S> sourceList, Class<T> targetObjectClass) {
        if (sourceList == null) {
            return Collections.EMPTY_LIST;
        }
        return sourceList.stream().map(s -> mapper.map(s, targetObjectClass)).collect(Collectors.toList());
    }

    /**
     * 找出 List 重复的元素
     * 
     * @param list 原集合列表
     * @param <E> 集合中的类型
     * @return 重复的元素列表
     */
    public static <E> List<E> getDuplicateElements(List<E> list) {
        if (list == null) {
            return Collections.EMPTY_LIST;
        }
        return list.stream()
            // 获得元素出现频率的 Map，键为元素，值为元素出现的次数
            .collect(Collectors.toMap(e -> e, e -> 1, Integer::sum))
            // 所有 entry 对应的 Stream
            .entrySet().stream()
            // 过滤出元素出现次数大于 1 (重复元素）的 entry
            .filter(e -> e.getValue() > 1)
            // 获得 entry 的键（重复元素）对应的 Stream
            .map(Map.Entry::getKey)
            // 转化为 List
            .collect(Collectors.toList());
    }

}
